<!-- eslint-disable no-unused-vars -->
<!-- eslint-disable vue/require-default-prop -->
<script type="text/babel">
import AutoNumeric from 'autonumeric/dist/autoNumeric.min';
const defaultOptions = {};

export default {
    name: 'AutoNumeric',
    props: {
        value: {
            required: false,
            validator(val) {
                return typeof val === 'number' || typeof val === 'string' || val === '' || val === null;
            }
        },
        options: {
            type: [Object, String, Array],
            required: false,
            default() {
                return defaultOptions;
            }
        },
        resetOnOptions: {
            type: Boolean,
            required: false,
            default: true
        },
        type: {
            type: String,
            required: false
        },
        placeholder: {
            type: String,
            required: false
        },
        tag: {
            type: String,
            required: false,
            default: 'input'
        },
        readOnly: {
            type: Boolean,
            required: false,
            default: false
        },
        isShowZero: {
            type: Boolean,
            required: false,
            default: true
        }
    },
    render(createElement) {
        const isInput = this.tag === 'input';
        let attributes;
        if (isInput) {
            attributes = {
                type: 'text',
                disabled: this.readOnly,
                placeholder: this.placeholder
            };
        } else {
            attributes = {
                contenteditable: this.hasContentEditable
            };
        }
        let className = 'el-input--mini el-input  ';
        if (this.readOnly) {
            className += 'is-disabled';
        }
        return createElement('div', { class: className }, [
            createElement(this.tag, {
                attrs: attributes,
                class: 'el-input__inner',
                style: 'text-align: right',
                ref: 'autoNumericElement',
                on: {
                    blur: this.blur,
                    'autoNumeric:rawValueModified': this.updateVModel,
                    keydown: this.keydown,
                    keyup: this.keyup,
                    change: this.change
                }
            })
        ]);
    },

    // eslint-disable-next-line vue/order-in-components
    data() {
        return {
            // Store the reference to the AutoNumeric object
            anElement: null,
            initialOptions: null, // Store the options that were first used when initializing the component
            hasContentEditable: true // Store if the element should be set as `contenteditable` on initialization
        };
    },
    // eslint-disable-next-line vue/order-in-components
    created() {
        /* if (Array.isArray(this.options)) {
            let optionObjects = {};
            this.options.forEach(optionElement => {
                this.initialOptions = this.manageOptionElement(optionElement);
                optionObjects = Object.assign(optionObjects, this.initialOptions); // Merge each options objects one after the other
            });

            this.initialOptions = optionObjects;
        } else {
            this.initialOptions = this.manageOptionElement(this.options);
        } */
        if (this.type) {
            console.log(this.type)
            let options = this.getAutonumericOption(this.type);
            this.initialOptions = this.getAutonumericOption(this.type);
        } else {
            this.initialOptions = this.manageOptionElement(this.options);
        }

        // Define if the generated non-input element should have the contenteditable attribute set to `true`
        this.hasContentEditable = !this.initialOptions.readOnly;
    },
    // eslint-disable-next-line vue/order-in-components
    mounted() {
        // Initialize the autoNumeric element
        this.anElement = new AutoNumeric(this.$refs.autoNumericElement, this.initialOptions);
        if (this.value !== null && this.value !== '') {
            this.anElement.set(this.value);
            // The `v-model` must be updated with that default value on startup
            // this.updateVModel();
        }
    },
    // eslint-disable-next-line vue/order-in-components
    computed: {
        /**
         * This computed property is created in order to be able to watch the changes to both `value` and `options` at the same time.
         * This is important since if both are changed at the same time, `options` needs to be updated *before* `value` (the order here is important, and is respected in the `anInfo` watcher).
         *
         * cf. https://github.com/vuejs/vue/issues/7723#issuecomment-369344926
         *
         * @returns {Object}
         */
        anInfo() {
            return {
                value: this.value,
                options: this.options
            };
        }
    },
    // eslint-disable-next-line vue/order-in-components
    methods: {
        blur() {
            let inputValue = '';
            if (this.isShowZero) {
                if (this.anElement.rawValue || this.anElement.rawValue === 0) {
                    inputValue = this.anElement.getNumber();
                }
            } else {
                if (!(!this.anElement.rawValue || this.anElement.rawValue === '0')) {
                    inputValue = this.anElement.getNumber();
                }
            }

            this.$emit('input', inputValue, event);
            this.changeNewVal(inputValue);

            this.$emit('blur');
        },
        keydown(event) {
            if (event.keyCode === 9) { // 禁用tab键
                event.returnValue = false;
            } else {
                this.$emit('keydown', event);
            }
        },
        keyup(event) {
            this.$emit('keyup', event);
        },
        change(event) {
            let inputValue = '';
            if (this.isShowZero) {
                if (this.anElement.rawValue || this.anElement.rawValue === 0) {
                    inputValue = this.anElement.getNumber();
                }
            } else {
                if (!(!this.anElement.rawValue || this.anElement.rawValue === '0')) {
                    inputValue = this.anElement.getNumber();
                }
            }

            this.$emit('input', inputValue, event);
            this.changeNewVal(inputValue);
            this.$emit('change', event);
        },
        getAutonumericOption(flag) {
            let option = {};
            if (flag == 'noaSep') {
                option = {
                    aSep: '' // 禁用千分位分隔符
                };
            } else if (flag === 'percent') {
                option = {
                    maximumValue: 100,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'percentMulTen') {
                option = {
                    maximumValue: 100,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    rawValueDivisor: 100,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === '%') {
                option = {
                    maximumValue: 100,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    suffixText: '%',
                    allowDecimalPadding: false,
                    rawValueDivisor: 100,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === '%2') {
                option = {
                    maximumValue: 100,
                    minimumValue: 0.0,
                    suffixText: '%',
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    rawValueDivisor: 100,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZ') {
                option = {
                    maximumValue: 999999999999999.99,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZZ') {
                option = {
                    maximumValue: 999999999999999,
                    minimumValue: 0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 0,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZZZ') {
                option = {
                    maximumValue: 999999999999999.99999999999,
                    minimumValue: -999999999999999.99999999999,
                    // modifyValueOnWheel: false,
                    // unformatOnHover: false,
                    allowDecimalPadding: false,
                    decimalPlaces: 11,
                };
            } else if (flag === 'jeF') {
                option = {
                    maximumValue: 0.0,
                    minimumValue: -999999999999999.99,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZf') {
                option = {
                    maximumValue: 999999999999999.99,
                    minimumValue: -999999999999999.99,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZf10D') {
                option = {
                    maximumValue: 9999999999.99,
                    minimumValue: -9999999999.99,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeOptionZF10') {
                option = {
                    maximumValue: 9999999999.99,
                    minimumValue: -9999999999.99,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'mjZ') {
                option = {
                    maximumValue: 999999999999.9999,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 4,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'mjF') {
                option = {
                    maximumValue: 0.0,
                    minimumValue: -999999999999.9999,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 4,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'mjZf') {
                option = {
                    maximumValue: 999999999999.9999,
                    minimumValue: -999999999999.9999,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 4,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeZ10') {
                option = {
                    maximumValue: 9999999999.99,
                    minimumValue: 0.0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    emptyInputBehavior: 'null'
                };
            } else if (flag === 'jeOptionZZ6') {
                option = {
                    maximumValue: 999999,
                    minimumValue: 0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 0,
                    emptyInputBehavior: 'null'
                };
            } else if (flag == 'cwOption') {
                option = {
                    decimalPlaces: '0'
                };
            } else if (flag == 'percent1w') {
                option = {
                    maximumValue: 10000,
                    minimumValue: 0.0,
                    suffixText: '%',
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    rawValueDivisor: 100,
                    emptyInputBehavior: 'null'
                };
            } else if (flag == 'jeOptionZS') {
                option = {
                    maximumValue: 999999999999999,
                    minimumValue: 0,
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    decimalPlaces: 0,
                    integerPos: true
                };
            } else if (flag == 'percentObjectFix4') {
                option = {
                    maximumValue: 100,
                    minimumValue: 0.0,
                    suffixText: '%',
                    modifyValueOnWheel: false,
                    unformatOnHover: false,
                    rawValueDivisor: 100,
                    decimalPlaces: 4
                };
            }
            return option;
        },
        /**
         * Update the v-model value and make the parent aware of that change.
         *
         * @param {Event} event This is needed if we want to use the `event.timeStamp` attribute
         */
        updateVModel(event) {
            console.log(event)
            if (this.anElement !== null) {
                console.log(event)
                // this.$emit('input', (event?.target.value === '') ? '' : this.anElement.getNumber(), event)
            }
        },
        changeNewVal(inputValue) {
            this.anElement.set(inputValue);
        },

        /**
         * Return an option object, whatever the type of `optionElement`.
         * If `optionElement` is as string, then we retrieve the predefined option object, if it's an object, we use it as is.
         *
         * @param {object|string} optionElement
         * @returns {object}
         */
        manageOptionElement(optionElement) {
            let options;
            if (typeof optionElement === 'string' || optionElement instanceof String) {
                options = AutoNumeric.getPredefinedOptions()[optionElement];
                if (options === void 0 || options === null) {
                    // If the given `optionElement` does not exist, we switch back to the default options
                    console.warn(`The given pre-defined options [${optionElement}] is not recognized by AutoNumeric.\nSwitching back to the default options.`);
                    options = defaultOptions; // Default value
                }
            } else {
                // A `settings` object
                options = optionElement;
            }

            return options;
        }
    },
    // eslint-disable-next-line vue/order-in-components
    watch: {
        anInfo(newValue, oldValue) {
            // 1) First, check if the options have changed, if that's the case, update those first
            // Compare the new and old options, and only update if they are different
            if (oldValue.options && JSON.stringify(newValue.options) !== JSON.stringify(oldValue.options)) {
                //TODO Find a better way (without external libraries) to compare the two options objects. Also, the comparison is moot when comparing 'euro' with the actual euro object.
                if (this.resetOnOptions) {
                    // This is needed when using predefined options that do not override previously used options
                    this.anElement.options.reset();
                }

                let optionsToUse;
                if (Array.isArray(newValue.options)) {
                    // Manage the new options if they are passed in an array
                    optionsToUse = AutoNumeric.mergeOptions(newValue.options);
                } else {
                    optionsToUse = AutoNumeric._getOptionObject(newValue.options);
                }

                this.anElement.update(optionsToUse);
            }

            // 2) Then check if the value has changed, if it's defined
            if (
                newValue.value !== void 0 &&
                // Make sure this is only called when the value is set by an external script, and not from a user input
                this.anElement.getNumber() !== newValue.value &&
                // Compare the 'newValue' with the current 'oldValue' so we do not `set` it again if it's not needed
                newValue.value !== oldValue.value
            ) {
                // The modification comes from a script, so we need to reformat the new value `newValue.value`
                this.anElement.set(newValue.value);
            }
        }
    }
};
</script>
